package wykop.analyze;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;

import wykop.page.WykopComment;
import wykop.parser.HibernateUtil;

import com.google.common.base.Charsets;
import com.google.common.collect.Maps;
import com.google.common.io.Files;

public class Bigrams {

	private final Map<StringPair, Integer> biFrequencies = Maps.newHashMap();
	private final Map<String, Integer> frequencies = Maps.newHashMap();
	private final double epsilon;
	public static final String FIRST = "$$$FIRST$$$";

	public static Bigrams create(final double epsilon) {
		final Bigrams bigrams = new Bigrams(epsilon);

		final Session session = HibernateUtil.getSessionFactory()
				.getCurrentSession();
		final List<WykopComment> comments = session.createCriteria(
				WykopComment.class).list();

		for (final WykopComment comment : comments) {
			String last = FIRST;
			for (final String token : WordBreaker.tokens(comment.getText())) {
				bigrams.increment(last, token);
				last = token;
			}
		}
		
		print(bigrams, "bigrams.log");

		return bigrams;
	}

	protected Bigrams(final double epsilon) {
		this.epsilon = epsilon;
		frequencies.put(FIRST, 0);
	}
	
	private final static void print(Bigrams bigram, String path)
	{
		Writer writer = null;
		try {
			writer = Files.newWriter(new File(path), Charsets.UTF_8);
			for(StringPair key : bigram.biFrequencies.keySet())
			{
				Integer value = bigram.biFrequencies.get( key );
				writer.write( key.getFirst() + " " + key.getSecond() + " " + value + "\n");
			}
			for(String key : bigram.frequencies.keySet())
			{
				Integer value = bigram.frequencies.get( key );
				writer.write( key + " " + value + "\n");
			}
		} catch (FileNotFoundException e) {
			throw new RuntimeException(e);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		finally
		{
			if( writer != null)
			{
				try {
					writer.close();
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
		}
		
		
	}

	public double getScores(final String first, final String second) {
		final StringPair pair = new StringPair(first, second);
		if (!biFrequencies.containsKey(pair)) {
			return epsilon;
		}
		final double s = biFrequencies.get(pair);
		final double f = frequencies.get(first);

		return s / f + epsilon;
	}

	protected void increment(final String first, final String second) {
		final StringPair pair = new StringPair(first, second);
		if (!biFrequencies.containsKey(pair)) {
			biFrequencies.put(pair, 0);
		}

		biFrequencies.put(pair, biFrequencies.get(pair) + 1);

		if (!frequencies.containsKey(second)) {
			frequencies.put(second, 0);
		}

		if (first.equals(Bigrams.FIRST)) {
			frequencies.put(first, frequencies.get(first) + 1);
		}

		frequencies.put(second, frequencies.get(second) + 1);
	}
}

class StringPair {
	private final String first;
	private final String second;

	public StringPair(final String first, final String second) {
		super();
		this.first = first;
		this.second = second;
	}

	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		final StringPair other = (StringPair) obj;
		if (first == null) {
			if (other.first != null) {
				return false;
			}
		} else if (!first.equals(other.first)) {
			return false;
		}
		if (second == null) {
			if (other.second != null) {
				return false;
			}
		} else if (!second.equals(other.second)) {
			return false;
		}
		return true;
	}

	public String getFirst() {
		return first;
	}

	public String getSecond() {
		return second;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (first == null ? 0 : first.hashCode());
		result = prime * result + (second == null ? 0 : second.hashCode());
		return result;
	}

}
